package domain;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import javax.json.Json;
import javax.json.stream.JsonParser;


public class JCDecauxJSonStreamParser {

	/**
	 * Parse the stream.
	 * 
	 * @param input
	 */
	public List<JCDecauxObject> parse(InputStream input) {

		JsonParser parser = Json.createParser(input);

		List<JCDecauxObject> result = new ArrayList<>(1200);
		ParserPath path = new ParserPath();
		JCDecauxObject currentObject = null;
		String keyName = null;
		while (parser.hasNext()) {
			JsonParser.Event event = parser.next();

			switch (event) {
			case START_ARRAY:
				path.push(event.name());
//				System.out.println("START_ARRAY:" + path);
				// arrayBuilder = factory.createArrayBuilder();
				// builderStack.addFirst(arrayBuilder);
				break;
			case END_ARRAY:
				path.pop();
//				System.out.println("END_ARRAY:" + path);
				// arrayBuilder = (JsonArrayBuilder) builderStack.removeFirst();
				// arrayBuilder.build();
				break;
			case START_OBJECT:
				path.push(event.name());
//				System.out.println("START_OBJECT:" + path);

				if (path.isPathEqualsTo("/START_ARRAY/START_OBJECT")) {
					currentObject = new JCDecauxObject();
					result.add(currentObject);
				}

				break;
			case END_OBJECT:
				path.pop();

				break;
			case KEY_NAME:
				keyName = parser.getString();

				break;

			case VALUE_FALSE:
			case VALUE_NULL:
			case VALUE_TRUE:
				break;
			case VALUE_STRING:
				if (path.isPathEqualsTo("/START_ARRAY/START_OBJECT")) {
					if (keyName.equals("status")) {
						EStatus stat = EStatus.strToValue(parser.getString());
						currentObject.setStatus(stat);
					}
				}
				break;
			case VALUE_NUMBER:

				if (path.isPathEqualsTo("/START_ARRAY/START_OBJECT")) {
					if (keyName.equals("number")) {
						currentObject.setNumber(parser.getInt());
					} else if (keyName.equals("bike_stands")) {
						currentObject.setBikeStands(parser.getInt());
					} else if (keyName.equals("available_bike_stands")) {
						currentObject.setAvailableBikeStands(parser.getInt());
					} else if (keyName.equals("available_bikes")) {
						currentObject.setAvailableBikes(parser.getInt());
					}
				}
				break;
			}
		}
		return result;
	}

	// ------------------------------------------------------------------------
	// -----------------------------------------------------------------------

	private static class ParserPath {
		private LinkedList<String> path = new LinkedList<String>();
		private String strPath = "";

		public void push(String item) {
			path.add(item);
			updateStrPath();
		}

		public void pop() {
			path.removeLast();
			updateStrPath();
		}

		private void updateStrPath() {
			StringBuilder sb = new StringBuilder();
			for (ListIterator<String> _it = path.listIterator(); _it.hasNext();) {
				sb.append("/").append(_it.next());
			}
			strPath = sb.toString();
		}

		public boolean isPathEqualsTo(String str) {
			return str.equals(strPath);
		}

		@Override
		public String toString() {
			return strPath;
		}
	}

}
